package com.jade.journal.impl;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Named;

import com.jade.framework.base.JadeSystem;
import com.jade.journal.Journal;
import com.jade.journal.JournalEvent;
import com.jade.journal.JournalHandler;
import com.jade.journal.JournalService;
import com.jade.journal.desc.AppenderDesc;
import com.jade.journal.desc.JournalDesc;
import com.jade.journal.desc.field.Field;
import org.apache.commons.digester3.Digester;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 日志服务的实现。
 *
 * @author Daisy
 * @version 1.0 14-9-21 下午8:52
 */
@Named ("system_journalService")
public class JournalServiceImpl implements JournalService, JournalHandler
{
    private Map<String, JournalHandler> handlerMap = new HashMap<String, JournalHandler>();
    private Map<String, JournalDesc> descMap = new HashMap<String, JournalDesc>();
    private String journalXml;
    private String journalHome;
    private Log log = LogFactory.getLog(JournalServiceImpl.class);

    public void setJournalXml(String journalXml)
    {
        this.journalXml = journalXml;
    }

    public void setHome(String journalHome)
    {
        this.journalHome = journalHome;
    }

    public void setHandlerMap(Map<String, JournalHandler> handlerMap)
    {
        this.handlerMap = handlerMap;
    }

    public void addDesc(JournalDesc desc)
    {
        descMap.put(desc.getName(), desc);
    }

    public String getHome()
    {
        if (StringUtils.isBlank(journalHome)) {
            journalHome = JadeSystem.getHome() + File.separator + "journal";
        }
        return journalHome;
    }

    public void start()
    {
        // allow expansion in both xml attributes and element text
        //Substitutor substitutor = new VariableSubstitutor(new JadeVariableExpander());
        Digester digester = new Digester();
        //digester.setSubstitutor(substitutor);
        try {
            digester.push(this);
            //digester.addObjectCreate("system", SystemDefinition.class);
            digester.addObjectCreate("journal/table", JournalDesc.class);
            digester.addSetProperties("journal/table");

            digester.addObjectCreate("journal/table/field", Field.class);
            digester.addSetProperties("journal/table/field");
            digester.addSetNext("journal/table/field", "addField");

            digester.addObjectCreate("journal/table/appender", AppenderDesc.class);
            digester.addSetProperties("journal/table/appender");
            digester.addCallMethod("journal/table/appender/property", "setProperty", 2);
            digester.addCallParam("journal/table/appender/property", 0, "name");
            digester.addCallParam("journal/table/appender/property", 1, "value");
            digester.addSetNext("journal/table/appender", "addAppenderDesc");
            digester.addSetNext("journal/table", "addDesc");
            digester.setValidating(false);
            if (StringUtils.isBlank(journalXml)) {
                journalXml = JadeSystem.getHome() + File.separator + "conf/journal.xml";
            }
            digester.parse(new File(journalXml));
        }
        catch (Throwable t) {
            log.error("Can't parse xml " + journalXml, t);
        }
    }

    public Journal getJournal(String name)
    {
        SimpleJournal journal = new SimpleJournal(name);
        //todo
        //journal.setLevel();
        journal.setHandler(this);
        return journal;
    }

    public void journal(JournalEvent... events)
    {
        for (JournalEvent event : events) {
            String name = event.getName();
            JournalDesc desc = descMap.get(name);
            if (desc == null) {
                log.error("Invalid journal : " + name);
                continue;
            }
            JournalHandler handler = getHandler(name);
            if (handler == null) {
                log.error("No handler for journal " + name);
                continue;
            }
            event.setDesc(desc);
            handler.handle(event);
        }
    }

    public void handle(JournalEvent... events)
    {
        journal(events);
    }

    protected JournalHandler getHandler(String name)
    {
        JournalHandler handler = handlerMap.get(name);
        if (handler == null) {
            handler = handlerMap.get("default");
        }
        return handler;
    }
}
